package com.ww.springboot.boot.thread.study.base.lock;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * await->等待  signal-》唤醒  顺序有要求
 * await 被唤醒后处于waiting状态 等待锁资源空闲 并不是一唤醒就能马上执行
 *
 * 公平锁 -》非公平锁
 * 公平锁 获取资源时 多一个判断 是否有比当前线程等待时间更长的线程 如果有则拿不到资源
 *
 * 获取资源-》根据锁队列顺序消费
 *
 * ReentrantLock -》可重入 如果当前线程与占用锁资源线程属于同一线程 则直接获取资源
 *
 */
public class LockDemo4 {


    Lock lock = new ReentrantLock();
    Condition conditionA = lock.newCondition();
    Condition conditionB = lock.newCondition();

    public void printA() throws InterruptedException {
        System.out.println("-------A入口------");
        //加锁
        lock.lock();
        try {
            System.out.println("-------A开始------");
            TimeUnit.SECONDS.sleep(3);
            //(await 会让出锁资源)
            conditionA.await();
            System.out.println("-------A解锁------");
            conditionB.await();
            System.out.println("-------B解锁------");
            System.out.println("-------A结束------");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            TimeUnit.SECONDS.sleep(5);
            // 释放锁
            System.out.println("-------释放锁1------");
            lock.unlock();
        }
    }

    public void printB() throws InterruptedException {
        System.out.println("-------B入口------");
        //加锁
        lock.lock();
        try {
            System.out.println("-------B开始------");
            TimeUnit.SECONDS.sleep(5);
            //(signal 唤醒await 当锁资源空闲时 await会继续执行)
            conditionA.signal();
            //conditionA.signal();
            System.out.println("-------B结束------");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            TimeUnit.SECONDS.sleep(5);
            // 释放锁
            System.out.println("-------释放锁2------");
            lock.unlock();
        }
    }

    public void printC() throws InterruptedException {
        TimeUnit.SECONDS.sleep(30);
        //加锁
        lock.lock();
        try {
            System.out.println("-------释放B------");
            conditionB.signal();
        } finally {
            lock.unlock();
        }
    }


    public static void main(String[] args) {
        LockDemo4 test = new LockDemo4();
        // 建立打印ABC的三个线程
        Thread theadA = new Thread(() -> {
            try {
                test.printA();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        Thread theadB = new Thread(() -> {
            try {
                test.printB();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        Thread theadC = new Thread(() -> {
            try {
                test.printC();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });

        // 启动线程
        theadA.start();
        theadB.start();
        theadC.start();
    }
}